<?php

namespace App\Http\Controllers\Admin\Product;

use App\Http\Controllers\Controller;
use App\Models\Category\Category;
use App\Models\Product;
use App\Models\ProductAttr;
use App\Models\ProductAttrResult;
use App\Models\ProductAttrValue;
use App\Models\ProductCate;
use App\Models\ProductCoupon;
use App\Models\ProductDescription;
use App\Models\ProductUserLabelRelation;
use App\Services\ProductService;
use App\Traits\Controllers\DestroyTraits;
use App\Traits\Controllers\RestoreTraits;
use App\Traits\Controllers\ShowTraits;
use App\Traits\Controllers\UpdateStatusTraits;
use App\Transformers\Product\ProductTransformer;
use Dingo\Api\Http\Response;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class ProductController extends Controller
{
    use UpdateStatusTraits;
    use DestroyTraits;
    use RestoreTraits;

    public $model = Product::class;

    public $transformer = ProductTransformer::class;

    public $productService;

    public function __construct()
    {
        parent::__construct();

        $this->productService = new ProductService();
    }

    /**
     * 首页列表信息
     */
    public function index(Request $request)
    {
        //处理传过来的搜索数据
        $this->formatIndexQuery($request);

        $deleted = $request->input('deleted');

        $category_id = $request->input('category_id');

        $data = $this
            ->getQuery()
            ->when($deleted, function ($q) {
                $q->onlyTrashed();
            })
            ->when($category_id, function ($q) use ($request, $category_id) {
                //判断得到的分类id为哪一级分类，分别重写request
                $level = Category::where('id', $category_id)->first()->level;

                switch ($level) {
                    case 1:
                        $request->offsetUnset('category_id');
                        $request->offsetSet('category:top_category_id', $category_id);
                        break;
                    case 2:
                        $category = Category::where('id', $category_id)->first()->children->pluck('id')->toArray();
                        $category_id = implode(',', $category);
                        $request->offsetSet('category:category_id', $category_id);
                        break;
                    case 3:
                        $request->offsetUnset('category_id');
                        $request->offsetSet('category:category_id', $category_id);
                        break;
                }
            })
            ->pimp()//自动转换where条件
            ->paginate($this->getPageLimit());

        return $this->response->paginator($data, resolve($this->transformer));
    }


    /**
     * 添加商品
     */
    public function store(Request $request)
    {

        $this->validateData($request);

        if ($request->input('spec_type') == 1) {

            $stock = 0;

            foreach($request->input('attr_result') as $ob){
                $stock += $ob['value'][0]['stock'];
            }

            $request->offsetSet('stock',$stock);

        }else{

            $request->offsetSet('stock',$request->input('product_attr_values')['stock']);
        }


        // 保存创建人
        $request->offsetSet('system_admin_id', $this->admin_user('id'));
        // 保存商户
        $request->offsetSet('mer_id', $this->admin_user('merchant_id') ?? 0);

        try {

            DB::beginTransaction();
            /**
             * 商品表添加
             */
            //先将商品表中的数据保存
            $model = $this->getQuery()->fill($request->all());
            $model->save();

            if (!$model->id) {
                throw  new  \Exception('添加商品失败');
            }

            /**
             * 商品分类中间表添加
             */

            //拿到前台传来的分类字符串
            $category = $request->input('category');

            $product_cate_bool = $this->productService->storeProductcate($category, $model);

            if (!$product_cate_bool) {
                throw  new  \Exception('商品分类中间表添加失败');
            }

            /**
             * 先判断是单轨格还是多规格
             */
            //如果是多规格，则执行多规格详情表添加
            if ($request->input('spec_type') == 1) {
                /**
                 * 商品多规格属性表添加
                 */
                //拿到前台传来的商品属性数组
                $attrs = $request->input('attr');

                $product_attr_bool = $this->productService->storeProductattr($attrs, $model);

                if (!$product_attr_bool) {
                    throw  new  \Exception('商品多规格属性表添加失败');
                }

                /**
                 * 商品多规格属性详情表添加
                 */
                $attr_results = $request->input('attr_result');

                $product_attr_result_bool = $this->productService->storeProductattrresult($attr_results, $model);

                if (!$product_attr_result_bool) {
                    throw  new  \Exception('商品多规格属性详情表添加失败');
                }

                //如果是单规格则执行单轨格详情表的添加
            } elseif ($request->input('spec_type') == 0) {

                $product_attr_values = $request->input('product_attr_values');

                $product_attr_values_bool = $this->productService->storeProdcutattrvalue($product_attr_values, $model);

                if (!$product_attr_values_bool) {
                    throw  new  \Exception('商品单规格属性详情表添加失败');
                }

            }


            /**
             * 商品详情表添加
             */
            $description = $request->input('descriptions');

            $product_descriptions_bool = $this->productService->storeProductdescription($description, $model);

            if (!$product_descriptions_bool) {
                throw  new  \Exception('商品详情表添加失败');
            }

            /**
             * 商品 用户标签 中间表添加
             */
            //判断是否传入用户标签
            $product_user_label = $request->input('product_user_label');

            if ($product_user_label) {

                $product_user_label_bool = $this->productService->storeProductuserlabel($product_user_label, $model);

                if (!$product_user_label_bool) {
                    throw  new  \Exception('商品用户标签中间表添加失败');
                }

            }


            /**
             * 商品赠送优惠券关联表添加
             */
            //判断是否传入赠送优惠id
            if ($request->input('issue_coupon_id')) {

                $issue_coupon_ids = array_filter(explode(',', $request->input('issue_coupon_id')));

                $product_coupon_bool = $this->productService->storeProductissuecouponids($issue_coupon_ids, $model);

                if (!$product_coupon_bool) {
                    throw  new  \Exception('商品赠送优惠券关联表添加失败');
                }
            }

            DB::commit();

        } catch (\Exception $exception) {

            DB::rollBack();

            report($exception);

            return $this->response->error('添加失败', 500);

        }

        return $this->response->created();

    }


    /**
     * 详情
     */
    public function show($id)
    {
        $data = $this->getQuery()->findOrFail($id);// findOrFail 查找失败时抛出异常404

        if ($this->policy) {
            $this->authorize('show', $data);
            // authorize 控制器授权  当你尝试授权一个动作并且在用户不允许执行给定动作时抛出授权异常
            //那么使用authorize()方法，会在异常时返回一个异常403响应错误。
        }

        return $this->response->item($data, resolve($this->transformer));
    }


    /**
     * 修改
     */
    public function update($id, Request $request)
    {
        $this->validateData($request);

        // 保存创建人
        $request->offsetSet('system_admin_id', $this->admin_user('id'));
        // 保存商户
        $request->offsetSet('mer_id', $this->admin_user('merchant_id') ?? 0);

        try {

            DB::beginTransaction();
            /**
             * 商品表修改
             */
            //执行商品表的修改
            $model = $this->getQuery()->where('id', $id)->first()->fill($request->all());
            $model->save();

            if (!$model->id) {
                throw  new  \Exception('修改商品失败');
            }


            /**
             * 商品分类中间表修改
             * 先删除，后修改
             */
            //拿到前台传来的分类字符串
            $category = $request->input('category');

            $product_cate_model = new ProductCate();

            //先删除中间表中的关联
            $product_cate_delete_bool = $product_cate_model->where('product_id', $model->id)->delete();

            if (!$product_cate_delete_bool) {
                throw  new  \Exception('删除中间表中的关联失败');
            }


            //然后执行中间表重新插入新的关联
            $product_cate_bool = $this->productService->storeProductcate($category, $model);

            if (!$product_cate_bool) {
                throw  new  \Exception('商品分类中间表修改失败');
            }

            /**
             * 先判断是单轨格还是多规格
             */
            //如果是多规格，先执行删除单规格的数据，然后修改多规格的数据
            if ($request->input('spec_type') == 1) {

                //先执行商品单轨格属性表删除
                $product_attr_values_model = new ProductAttrValue();
                $product_attr_values_delete_bool = $product_attr_values_model->where('product_id', $model->id)->delete();

                if (!$product_attr_values_delete_bool && $product_attr_values_delete_bool !== 0) {
                    throw  new  \Exception('商品单轨格属性表删除失败');
                }

                /**
                 * 商品多规格属性表修改
                 * 先删后加
                 */
                //拿到前台传来的商品属性数组
                $attrs = $request->input('attr');

                //执行商品多规格属性表修改,先删后加
                $product_attr = new ProductAttr();
                $product_attr_delete_bool = $product_attr->where('product_id', $model->id)->delete();

                if (!$product_attr_delete_bool && $product_attr_delete_bool !== 0) {
                    throw  new  \Exception('商品多规格属性表删除失败');
                }

                $product_attr_bool = $this->productService->storeProductattr($attrs, $model);

                if (!$product_attr_bool) {
                    throw  new  \Exception('商品分类中间表修改失败');
                }

                /**
                 * 商品多规格属性详情表修改
                 */
                $attr_results = $request->input('attr_result');

                //执行商品多规格属性详情表插入,先删后改
                $product_attr_result = new ProductAttrResult();
                $product_attr_result_delete_bool = $product_attr_result->where('product_id', $model->id)->delete();

                if (!$product_attr_result_delete_bool && $product_attr_result_delete_bool !== 0) {
                    throw  new  \Exception('商品多规格属性详情表删除失败');
                }

                $product_attr_result_bool = $this->productService->storeProductattrresult($attr_results, $model);

                if (!$product_attr_result_bool) {
                    throw  new  \Exception('商品多规格属性详情表修改失败');
                }

                //如果是单规格则执行单轨格详情表的添加
            } elseif ($request->input('spec_type') == 0) {

                /**
                 * 先删除多规格的商品属性以及属性详情
                 */
                //执行商品多规格属性表删除
                $product_attr = new ProductAttr();
                $product_attr_delete_bool = $product_attr->where('product_id', $model->id)->delete();

                if (!$product_attr_delete_bool && $product_attr_delete_bool !== 0) {
                    throw  new  \Exception('商品多规格属性表删除失败');
                }

                //执行商品多规格属性详情表删除
                $product_attr_result_model = new ProductAttrResult();
                $product_attr_result_delete_bool = $product_attr_result_model->where('product_id', $model->id)->delete();

                if (!$product_attr_result_delete_bool && $product_attr_result_delete_bool !== 0) {
                    throw  new  \Exception('商品多规格属性详情表删除失败');
                }

                //执行商品单规格属性详情表删除
                $product_attr_values_model = new ProductAttrValue();
                $product_attr_values_delete_bool = $product_attr_values_model->where('product_id', $model->id)->delete();

                if (!$product_attr_values_delete_bool && $product_attr_values_delete_bool !== 0) {
                    throw  new  \Exception('商品单规格属性详情表删除失败');
                }

                /**
                 * 商品单规格属性详情表修改
                 */
                $product_attr_values = $request->input('product_attr_values');

                //执行商品单轨格属性表插入
                $product_attr_values_bool = $this->productService->storeProdcutattrvalue($product_attr_values, $model);

                if (!$product_attr_values_bool) {
                    throw  new  \Exception('商品单规格属性详情表修改失败');
                }

            }

            /**
             * 商品详情表修改
             */
            $description = $request->input('descriptions');

            $descriptions['description'] = $description;

            //执行商品详情表插入
            $product_description = new ProductDescription();
            $product_description_model = $product_description->where('product_id', $model->id)->first()->fill($descriptions);
            $product_description_model->save();

            if (!$product_description_model->id) {
                throw  new  \Exception('商品详情表修改失败');
            }


            /**
             * 商品 用户标签 中间表修改
             * 先删除，后添加
             */
            $product_user_label = $request->input('product_user_label');

            //判断是否传入用户标签
            if (!empty($product_user_label)) {

                //先删除
                $product_user_label_model = new ProductUserLabelRelation();
                $product_user_label_delete_bool = $product_user_label_model->where('product_id', $model->id)->delete();

                if (!$product_user_label_delete_bool && $product_user_label_delete_bool !== 0) {
                    throw  new  \Exception('商品用户标签中间表修改失败');
                }

                //执行中间表插入
                $product_user_label_bool = $this->productService->storeProductuserlabel($product_user_label, $model);

                if (!$product_user_label_bool) {
                    throw  new  \Exception('商品用户标签中间表修改失败');
                }

            } else {

                //只删除
                $product_user_label_model = new ProductUserLabelRelation();
                $product_user_label_delete_bool = $product_user_label_model->where('product_id', $model->id)->delete();

                if (!$product_user_label_delete_bool && $product_user_label_delete_bool !== 0) {
                    throw  new  \Exception('商品用户标签中间表修改失败');
                }

            }

            /**
             * 商品赠送优惠券关联表修改
             * 先删除，后添加
             */
            $product_coupon = $request->input('issue_coupon_id');

            //判断是否传入赠送优惠id
            if (!empty($product_coupon)) {

                //先删除
                $product_coupon_model = new ProductCoupon();
                $product_coupon_delete_bool = $product_coupon_model->where('product_id', $model->id)->delete();

                if (!$product_coupon_delete_bool && $product_coupon_delete_bool !== 0) {
                    throw  new  \Exception('商品赠送优惠券关联表删除失败');
                }

                //将字符串拆分成数组，并过滤掉空的元素
                $issue_coupon_ids = array_filter(explode(',', $product_coupon));

                //执行关联表插入
                $product_coupon_bool = $this->productService->storeProductissuecouponids($issue_coupon_ids, $model);

                if (!$product_coupon_bool) {
                    throw  new  \Exception('商品赠送优惠券关联表修改失败');
                }

            } else {

                //只删除
                $product_coupon_model = new ProductCoupon();
                $product_coupon_delete_bool = $product_coupon_model->where('product_id', $model->id)->delete();

                if (!$product_coupon_delete_bool && $product_coupon_delete_bool !== 0) {
                    throw  new  \Exception('商品赠送优惠券关联表删除失败');
                }

            }

            DB::commit();

        } catch (\Exception $exception) {

            DB::rollBack();

            report($exception);

            return $this->response->error('修改失败', 500);

        }

        return $this->response->noContent();
    }

    /**
     * 获取顶部标签
     * @return array[]
     */
    public function get_header()
    {
        //onsale出售中的商品数量,forsale仓库中的商品数量,outofstock已经售馨商品数量,policeforce警戒库存商品数量
        $counts = $this->getQuery()
            ->selectRaw("COUNT(DISTINCT IF(status=1,id,NULL)) as onsale,COUNT(DISTINCT IF(status=0,id,NULL)) as forsale,COUNT(DISTINCT IF(stock=0,id,NULL)) as outofstock,COUNT(DISTINCT IF(stock<=100,id,NULL)) as policeforce")
            ->get();

        //回收站中商品的数量
        $recycle = $this->getQuery()->onlyTrashed()->count();

        $data = [
            ['status' => 1, 'name' => '出售中的商品', 'count' => $counts[0]->onsale],
            ['status' => 0, 'name' => '仓库中的商品', 'count' => $counts[0]->forsale],
            ['stock' => 0, 'name' => '已经售馨商品', 'count' => $counts[0]->outofstock],
            ['stock' => '(lt)100', 'name' => '警戒库存商品', 'count' => $counts[0]->policeforce],
            ['deleted' => 'deleted', 'name' => '回收站的商品', 'count' => $recycle]
        ];
        return new Response(compact('data'), 200);
    }


    /**
     * 参数验证规则
     *
     * @param Request $request
     * @return array
     */
    public function rules(Request $request): array
    {
        switch ($request->method()) {
            case 'GET':
                return [];
                break;
            case 'PATCH':
            case 'POST':
                return [
                    'product_name' => 'bail|required',
                    'category' => 'bail|required',
                    'unit_name' => 'bail|required',
                    'image' => 'bail|required',
                    'temp_id' => 'bail|required',
                    'slider_image' => 'bail|required|array',
                    'spu' => 'bail|required',
                    'spec_type' => 'bail|required',
                    'product_attr_values' => 'bail|nullable|array',
                    'attr_result' => 'bail|nullable|array',
                    'attr' => 'bail|nullable|array'
                ];
                break;
            case 'PUT':
                return [
                    'status' => 'bail|required',
                    'ids' => 'bail|required'
                ];
                break;
        }
        return [];
    }

    /**
     * 验证信息
     *
     * @return array
     */
    public function ruleMessages(): array
    {
        return [
            'product_name.required' => '商品名称 不能为空',
            'category.required' => '分类 不能为空',
            'temp_id.required' => '运费模板 不能为空',
            'image.required' => '商品封面图片 不能为空',
            'image.array' => '商品封面图片 传参类型错误',
            'slider_image.required' => '商品轮播图 不能为空',
            'unit_name.required' => '单位 不能为空',
            'spu.required' => 'SPU 不能为空',
            'deleted_at.required' => '是否删除 不能为空',
            'status.required' => '状态 不能为空',
            'ids.required' => 'id 不能为空'
        ];
    }

}
